#!/bin/bash

# OpenCloudOS 节点管理工具 - 全面测试脚本

set -euo pipefail  # 严格模式：遇到错误退出，未定义变量报错，管道错误传播

echo "🧪 OpenCloudOS 节点管理工具 - 全面测试"
echo "======================================="

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 测试结果统计
PASS_COUNT=0
FAIL_COUNT=0

# 记录测试结果
log_test() {
    local test_name="$1"
    local result="$2"
    local message="$3"
    
    if [ "$result" = "PASS" ]; then
        echo -e "${GREEN}✅ PASS${NC}: $test_name - $message"
        PASS_COUNT=$((PASS_COUNT + 1))
    else
        echo -e "${RED}❌ FAIL${NC}: $test_name - $message"
        FAIL_COUNT=$((FAIL_COUNT + 1))
    fi
}

# 等待服务启动
wait_for_service() {
    local service_name="$1"
    local port="$2"
    local max_wait=30
    
    echo "⏳ 等待 $service_name 启动 (端口 $port)..."
    for i in $(seq 1 $max_wait); do
        if nc -z localhost $port 2>/dev/null; then
            echo -e "${GREEN}✅ $service_name 已启动${NC}"
            return 0
        fi
        sleep 1
    done
    
    echo -e "${RED}❌ $service_name 启动超时${NC}"
    return 1
}

# 强力清理函数
force_cleanup() {
    echo "🧹 强力清理环境..."
    # 停止所有相关进程
    pkill -f "node_server" 2>/dev/null || true
    pkill -f "node_agent" 2>/dev/null || true
    
    # 清理所有临时日志文件 - 包含所有生成的测试文件
    rm -f server.log agent_*.log comprehensive_*.log test_file.txt /tmp/test_*.txt
    rm -f agent1.log agent2.log agent3.log agent4.log
    rm -f hostname_all.log hostname_web.log script_db.log
    rm -f send_file.log verify_file.log db_status.log rabbitmq_status.log
    rm -f perf_test_*.log
    rm -f *.pid nohup.out
    
    # 强制杀死残留进程  
    pkill -9 -f "node_server" 2>/dev/null || true
    pkill -9 -f "node_agent" 2>/dev/null || true
    
    sleep 3
    echo "✅ 环境清理完成"
}

# 错误处理函数
handle_error() {
    local line_no=$1
    echo -e "${RED}❌ 测试在第 $line_no 行失败！${NC}"
    force_cleanup
    exit 1
}

# 注册错误处理
trap 'handle_error $LINENO' ERR

# 开始测试前清理环境
force_cleanup

echo "🏗️  步骤1: 编译项目"
echo "========================"
if cargo build --release; then
    log_test "项目编译" "PASS" "所有组件编译成功"
else
    log_test "项目编译" "FAIL" "编译失败"
    exit 1
fi

echo
echo "🐳 步骤2: 启动基础设施"
echo "========================"
echo "启动RabbitMQ和PostgreSQL..."
cd deploy
# 检查 PostgreSQL 是否有数据卷冲突
if docker compose ps -q postgresql | xargs -r docker inspect -f '{{.State.Status}}' 2>/dev/null | grep -q restarting; then
    echo "⚠️  检测到 PostgreSQL 重启循环，正在重置数据卷..."
    docker compose down
    docker volume rm deploy_postgres_data 2>/dev/null || true
fi
if ! docker compose up -d; then
    cd ..
    log_test "基础设施启动" "FAIL" "Docker容器启动失败"
    exit 1
fi
cd ..
log_test "基础设施启动" "PASS" "Docker容器启动成功"

# 等待服务启动
wait_for_service "RabbitMQ" "5672"
wait_for_service "PostgreSQL" "5432"
wait_for_service "RabbitMQ管理界面" "15672"

echo
echo "🚀 步骤3: 启动Node Server"
echo "========================"
# 启动Server (后台运行)
echo "启动 Node Server..."
nohup ./target/release/node_server start > server.log 2>&1 &
SERVER_PID=$!
echo "Node Server PID: $SERVER_PID"

# 等待Server启动
sleep 3
if ps -p $SERVER_PID > /dev/null; then
    log_test "Node Server启动" "PASS" "Server进程正在运行 (PID: $SERVER_PID)"
else
    log_test "Node Server启动" "FAIL" "Server进程未启动"
    cat server.log
    exit 1
fi

echo
echo "🤖 步骤4: 多Agent测试"
echo "====================="

# 启动多个Agent实例模拟不同的节点
declare -a AGENT_PIDS=()

# Agent 1: web组
echo "启动 Agent-1 (web组)..."
nohup ./target/release/node_agent --groups web --token secure_token_123 > agent1.log 2>&1 &
AGENT1_PID=$!
AGENT_PIDS+=($AGENT1_PID)

# Agent 2: database组  
echo "启动 Agent-2 (database组)..."
nohup ./target/release/node_agent --groups database --token secure_token_123 > agent2.log 2>&1 &
AGENT2_PID=$!
AGENT_PIDS+=($AGENT2_PID)

# Agent 3: 多组
echo "启动 Agent-3 (web,cache组)..."
nohup ./target/release/node_agent --groups web,cache --token secure_token_123 > agent3.log 2>&1 &
AGENT3_PID=$!
AGENT_PIDS+=($AGENT3_PID)

# Agent 4: 无效Token测试
echo "启动 Agent-4 (无效Token)..."
nohup ./target/release/node_agent --groups test --token invalid_token > agent4.log 2>&1 &
AGENT4_PID=$!
AGENT_PIDS+=($AGENT4_PID)

# 等待Agent注册
sleep 5

# 检查Agent状态
for i in "${!AGENT_PIDS[@]}"; do
    pid=${AGENT_PIDS[$i]}
    agent_num=$((i+1))
    if ps -p $pid > /dev/null; then
        log_test "Agent-$agent_num进程" "PASS" "Agent进程正在运行 (PID: $pid)"
    else
        log_test "Agent-$agent_num进程" "FAIL" "Agent进程未运行"
        cat "agent$agent_num.log" | tail -10
    fi
done

echo
echo "💫 步骤5: 功能测试"
echo "==================="

# 测试1: 获取主机名 (所有组)
echo "测试1: 获取所有节点主机名..."
if timeout 10s ./target/release/node_server command get-hostname > hostname_all.log 2>&1; then
    log_test "获取主机名(全部)" "PASS" "命令执行成功"
else
    log_test "获取主机名(全部)" "FAIL" "命令执行失败"
    cat hostname_all.log
fi

sleep 2

# 测试2: 获取主机名 (web组)
echo "测试2: 获取web组节点主机名..."
if timeout 10s ./target/release/node_server command --group web get-hostname > hostname_web.log 2>&1; then
    log_test "获取主机名(web组)" "PASS" "命令执行成功"
else
    log_test "获取主机名(web组)" "FAIL" "命令执行失败"
    cat hostname_web.log
fi

sleep 2

# 测试3: 执行脚本 (database组)
echo "测试3: 在database组执行脚本..."
if timeout 15s ./target/release/node_server command --group database run-script \
    --script "echo 'Hello from database node'; uname -a; date" \
    --timeout 10 > script_db.log 2>&1; then
    log_test "执行脚本(database组)" "PASS" "脚本执行成功"
else
    log_test "执行脚本(database组)" "FAIL" "脚本执行失败"
    cat script_db.log
fi

sleep 2

# 测试4: 文件发送测试
echo "测试4: 发送文件到web组..."
echo "这是一个测试文件内容" > test_file.txt
if timeout 15s ./target/release/node_server command --group web send-file \
    --local-path "./test_file.txt" \
    --remote-path "/tmp/test_file.txt" > send_file.log 2>&1; then
    log_test "发送文件(web组)" "PASS" "文件发送成功"
else
    log_test "发送文件(web组)" "FAIL" "文件发送失败"
    cat send_file.log
fi

sleep 2

# 测试5: 验证文件是否接收成功
echo "测试5: 验证文件接收..."
if timeout 10s ./target/release/node_server command --group web run-script \
    --script "if [ -f /tmp/test_file.txt ]; then echo 'File exists'; cat /tmp/test_file.txt; else echo 'File not found'; fi" \
    --timeout 10 > verify_file.log 2>&1; then
    log_test "验证文件接收" "PASS" "文件验证成功"
else
    log_test "验证文件接收" "FAIL" "文件验证失败"
    cat verify_file.log
fi

echo
echo "📊 步骤6: 数据库状态检查"
echo "========================"

# 检查数据库中的Agent状态
echo "检查数据库中注册的Agent..."
cd deploy
if docker exec -e PGPASSWORD=admin123 $(docker compose ps -q postgresql) \
    psql -h localhost -U admin -d node_management \
    -c "SELECT agent_id, hostname, groups, status, last_heartbeat FROM agents ORDER BY last_heartbeat DESC;" \
    > ../db_status.log 2>&1; then
    cd ..
    log_test "数据库状态查询" "PASS" "成功查询Agent状态"
    echo "数据库状态:"
    cat db_status.log
else
    cd ..
    log_test "数据库状态查询" "FAIL" "数据库查询失败"
    cat db_status.log
fi

echo
echo "🌐 步骤7: RabbitMQ状态检查" 
echo "========================"

# 检查RabbitMQ队列状态
echo "检查RabbitMQ队列状态..."
if curl -s -u admin:admin123 "http://localhost:15672/api/queues" > rabbitmq_status.log 2>&1; then
    log_test "RabbitMQ状态查询" "PASS" "成功查询队列状态"
    echo "活跃队列数量: $(cat rabbitmq_status.log | grep -o '"name"' | wc -l)"
else
    log_test "RabbitMQ状态查询" "FAIL" "RabbitMQ查询失败"
fi

echo
echo "⏱️  步骤8: 性能压力测试"
echo "======================"

# 批量发送命令测试
echo "发送10个并发hostname命令..."

# 使用数组记录后台进程PID
declare -a perf_pids=()

# 并发执行命令
for i in {1..10}; do
    timeout 15s ./target/release/node_server command get-hostname > "perf_test_$i.log" 2>&1 &
    perf_pids+=($!)
done

# 等待所有命令完成
echo "等待命令完成..."
all_completed=true
for pid in "${perf_pids[@]}"; do
    if ! wait "$pid"; then
        echo "警告: 进程 $pid 未正常完成"
        all_completed=false
    fi
done

# 统计成功的命令数量
success_count=0
for i in {1..10}; do
    if [ -f "perf_test_$i.log" ] && grep -q "Task.*sent" "perf_test_$i.log"; then
        success_count=$((success_count + 1))
    fi
done

if [ $success_count -ge 8 ]; then
    log_test "并发性能测试" "PASS" "$success_count/10个并发命令成功"
else
    log_test "并发性能测试" "FAIL" "只有$success_count/10个命令成功"
fi

echo
echo "🔒 步骤9: 安全测试"
echo "=================="

# 检查无效Token的Agent是否被拒绝
echo "检查无效Token Agent状态..."
sleep 2
if grep -q "Invalid token" server.log; then
    log_test "Token验证" "PASS" "无效Token被正确拒绝"
else
    log_test "Token验证" "FAIL" "Token验证可能存在问题"
    echo "Server日志中的Token相关信息:"
    grep -i "token\|auth" server.log | tail -5 || echo "未找到相关日志"
fi

echo
echo "📈 步骤10: 监控和日志"
echo "===================="

# 收集系统信息
echo "系统资源使用情况:"
echo "内存使用:"
ps aux | grep -E "(node_server|node_agent)" | grep -v grep | awk '{print $2, $3, $4, $11}' || true

echo "网络连接:"
netstat -tulpn | grep -E "(5672|5432)" || true

echo
echo "📋 测试总结"
echo "==========="
echo -e "总测试数量: $((PASS_COUNT + FAIL_COUNT))"
echo -e "${GREEN}通过: $PASS_COUNT${NC}"
echo -e "${RED}失败: $FAIL_COUNT${NC}"

# 最终清理
echo "🧹 执行最终清理..."
force_cleanup

if [ $FAIL_COUNT -eq 0 ]; then
    echo -e "${GREEN}🎉 所有测试通过！系统运行正常！${NC}"
    exit 0
else
    echo -e "${RED}⚠️  有 $FAIL_COUNT 个测试失败，请检查日志${NC}"
    exit 1
fi
